package com.szeldon.pj.jps.exp;

import java.util.List;

import com.szeldon.pj.jps.data.store.SBAStore;
import com.szeldon.pj.jps.datastore.SimpleObject;
import com.szeldon.pj.jps.envs.ENVS;
import com.szeldon.pj.jps.envs.ENVSBinder;
import com.szeldon.pj.jps.envs.ENVSStackFrame;
import com.szeldon.pj.jps.qres.AbstractQueryResult;
import com.szeldon.pj.jps.qres.BagResult;
import com.szeldon.pj.jps.qres.BooleanResult;
import com.szeldon.pj.jps.qres.QResStack;
import com.szeldon.pj.jps.visitor.ASTVisitor;

public class WhereExpression extends BinaryExpression {

	/**
	 * 
	 * @param leftExpression
	 * @param rightExpression
	 */
	public WhereExpression(Expression leftExpression, Expression rightExpression) {
		super(leftExpression, rightExpression);
	}

	/**
	 * 
	 * @param astVisitor
	 * @param envs
	 * @param qResStack
	 * @param store
	 */
	public void accept(ASTVisitor astVisitor, ENVS envs, QResStack qResStack, SBAStore store) {
		astVisitor.accept(leftExpression);

		BagResult expressionResult = new BagResult();

		AbstractQueryResult qResStackPoppedResult = qResStack.pop();
		if (!(qResStackPoppedResult instanceof BagResult)) {
			throw new IllegalStateException("Where expression expects result of left subexpression to be of "
					+ "BagResult type. Currently it is " + qResStackPoppedResult.getClass().getName() + ".");
		}

		BagResult leftResultsBag = (BagResult) qResStackPoppedResult;
		for (AbstractQueryResult currentLeftResult : leftResultsBag.getElements()) {
			List<ENVSBinder> bindersList = envs.nested(currentLeftResult, store);
			envs.push(new ENVSStackFrame(bindersList));

			astVisitor.accept(rightExpression);
			AbstractQueryResult currentRightResult = qResStack.pop();
			if (!(currentRightResult instanceof BooleanResult)) {
				throw new IllegalStateException(
						"Where expression expects boolean result of his right expression. Currently it is "
								+ currentRightResult.getClass().getName() + ".");
			}
			if (((BooleanResult) currentRightResult).getBool()) {
				expressionResult.addResult(currentLeftResult);
			}
			envs.pop();
		}

		qResStack.push(expressionResult);
	}

	@Override
	public int compareTo(SimpleObject object) throws IllegalStateException {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public String getValueAsString() {
		return "where";
	}

}
